"""Curses UI. Text-based UI, available by default on Unix.

To use on windows, first download and install the wheel file for curses.
"""

import curses
import time

from ui.abstract import AbstractUI


class CursesUI(AbstractUI):
    """Curses UI main class."""
    def __init__(self, state):
        super(CursesUI, self).__init__(state)

        self._screen = curses.initscr()
        self._screen.nodelay(1)
        curses.noecho()
        curses.cbreak()
        curses.curs_set(0)
        self._screen.keypad(True)

        self._pad = curses.newpad(self.maze.sizeY + 2, self.maze.sizeX + 2)
        self._sidebar = curses.newwin(15, 20, 0, self.maze.sizeX + 2)
        self._screen_y, self._screen_x = self._screen.getmaxyx()

        self._last_time = time.time()
        self.fps = 0

    def wait(self):
        super().wait()

        time_diff = time.time() - self._last_time
        self.fps = 0.9 * self.fps + 0.1 / time_diff
        self._last_time += time_diff

    def terminate(self):
        curses.nocbreak()
        self._screen.keypad(False)
        curses.curs_set(2)
        curses.echo()
        curses.endwin()

    def poll(self):
        c = self._screen.getch()

        # Movement event
        me = self._get_event_from_char(chr(c))
        if me is not None:
            yield me

    def _draw_entity(self, ent, char):
        self._pad.addch(
            ent.location[1] + 1,
            ent.location[0] + 1,
            ord(char)
        )

    def draw(self):
        for x in range(self.maze.sizeX):
            for y in range(self.maze.sizeY):
                if self.maze[x, y]:
                    self._pad.addch(y + 1, x + 1, ord(' '))
                else:
                    self._pad.addch(y + 1, x + 1, ord('#'))

        self._draw_entity(self.state.player, '@')
        for enemy in self.state.enemies:
            self._draw_entity(enemy, '&')
        self._pad.border()

        self._pad.refresh(0, 0, 0, 0, min(
            self.maze.sizeY + 2, self._screen_y - 1
        ), self.maze.sizeX + 2)

        self._sidebar.clear()
        self._sidebar.addstr(1, 1, 'FPS: {}'.format(round(self.fps)))

        for i, k in enumerate(self._get_key_help().items()):
            self._sidebar.addstr(2 + i, 1, '{}: {}'.format(k[0], k[1]))
        self._sidebar.border()
        self._sidebar.refresh()
